#!/usr/bin/env bash

source ../../lib/shell/common.sh

function setup() {
	echo "check test tool rpm before test"
	ip link help vlan&> /dev/null || { echo "iproute is not installed";exit 1; }
}

function check_link_state() {
	local link_state=$1
	local interface=$2

	for ((i=0; i<5; i++)); do
		sleep 5
		if [ "$link_state" == "up" ]; then
			if ip link show "$interface" | grep -q "UP"; then
				echo "$interface ip link state is $link_state"
				break
			fi
		else
			if ! ip link show "$interface" | grep -q "UP"; then
				echo "$interface ip link state is $link_state"
				break
			fi
		fi
	done

	if [ $i -eq 5 ]; then
		echo "test $interface $link_state failed"
		test_fail
	fi
}

function check_phy_link_state() {
	local link_state=$1
	local interface=$2

	if [ "$link_state" == "up" ]; then
		link_state_str="Link detected: yes"
	else
		link_state_str="Link detected: no"
	fi
	for ((i=0; i<5; i++)); do
		sleep 5
		if ethtool "$interface" | grep -q "$link_state_str"; then
			echo "$interface ethtool link state is $link_state"
			break
		fi
	done

	if [ $i -eq 5 ]; then
		echo "test $interface $link_state failed"
		test_fail
	fi
}

function check_dhcp_conf() {
	local interface=$1
	local net_path="/etc/sysconfig/network-scripts/ifcfg-$interface"

        echo "start check $interface dhcp config"

        if [ ! -f $net_path ]; then
                echo "$net_path is not exist" && return 2
        fi

	grep -v "[[:space:]]*#" $net_path | grep "BOOTPROTO" | grep "dhcp"
	if [ $? -eq 0 ]; then
		echo "$interface is dhcp ip, start to check NetworkManager status"
		systemctl status NetworkManager | awk '/Active: active/'
		if [ $? -eq 0 ]; then
			echo "NetworkManager is active, dhcp check success" && return 0
		else
			dhclient --version
			if [ $? -eq 0 ]; then
				echo "NetworkManager is not active, use dhclient to get ip address after set $interface up" && return 1
			else
				echo "$interface dhcp NetworkManager is not active, and dhclient is not installed" && return 2
			fi
		fi
	else
		echo "$interface is not dhcp ip" && return 2
	fi
}

function setstatus() {
	echo "run network status set test!"
	ifconfig
	ip link show
	interfaces=$INTERFACES

        while read line; do
		echo "exclude interface: $line"
  	    	interfaces=( ${interfaces[*]/$line} )
	done <../../../etc/exclude_interface

	for interface in ${interfaces[*]}; do
		local dhcp_status=0
                local ip_line=`ifconfig $interface | grep "inet"`
                echo ${ip_line%netmask*} | grep -o "[0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}"
                if [ $? -eq 0 ]; then
                        check_dhcp_conf "$interface"
                        dhcp_status=$?
                        if [ $dhcp_status -eq 2 ]; then
                                echo "$interface dhcp conf check failed, skip set status test"
                                continue
                        fi
                else
                        echo "$interface ip is not configed, start test down up directly"
                fi

		local check_interface_phy_link=false
		echo "set $interface link to up"
		ip link set "$interface" up
		if ethtool "$interface" | grep -q "Link detected: yes"; then
			echo "$interface physical link state: yes"
			local check_interface_phy_link=true
		fi

		echo "test interface: $interface"
		ip link set "$interface" down
		check_link_state "down" "$interface"
		if $check_interface_phy_link; then
			check_phy_link_state "down" "$interface"
		fi

		ip link set "$interface" up
		check_link_state "up" "$interface"
		if $check_interface_phy_link; then
			check_phy_link_state "up" "$interface"
		fi

		if [ $dhcp_status -eq 1 ]; then
			ip_line=`ifconfig $interface | grep "inet"`
			echo ${ip_line%netmask*} | grep -o "[0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}"
			if [ $? -ne 0 ]; then
				local cnt=1
				while [ $cnt -le 3 ]; do
					timeout 10 dhclient $interface
					if [ $? -eq 0 ]; then
						echo "$interface dhcp ip get success" && break
					elif [ $cnt -eq 3 ]; then
						echo "$interface dhcp ip get failed, please config it by yourself"
					fi
					cnt=$(($cnt+1))
				done
			fi
		fi
	done
}

function run_network_test() {
	setup
	setstatus
}

# # # # # # # # # # # # # # main # # # # # # # # # # # # # #
print_test_info "Network"
show_network_info
run_network_test
test_pass
